package com.hllxd.hism.passport.base.client;

import com.alibaba.fastjson.JSONObject;
import com.hllxd.hism.passport.base.config.passport.PassportProperties;
import com.hllxd.hism.passport.base.error.PassportErrorCode;
import com.hllxd.hism.passport.base.model.PlatUser;
import com.hllxd.hism.passport.base.model.PlatUserHolder;
import com.hllxd.hism.passport.base.redis.AccessTokenRedisMapper;
import com.hllxd.hism.passport.base.util.PassportUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;

@Component public class PassportInterceptor extends HandlerInterceptorAdapter {
    private static Logger log = LoggerFactory.getLogger(PassportInterceptor.class);

    @Autowired private PassportProperties passportProperties;

    @Autowired private AccessTokenRedisMapper accessTokenRedisMapper;

    public String getAccessToken(HttpServletRequest request) {
        String tokenValue = null;
        String plat = request.getParameter("plat");
        if(! StringUtils.isEmpty(plat)) {
            if(Integer.parseInt(plat) == 1) {
                tokenValue = request.getParameter("access_token");
            }
        } else {
            tokenValue = request.getParameter("token");
            if(tokenValue==null)  {
                tokenValue = this.getCookieValue(request, "access_token");
            }
        }
        return tokenValue;
    }
    public String getCookieValue(HttpServletRequest request, String cookieKey) {
        Cookie[] cookies = request.getCookies();
        String tokenValue = null;
        if(cookies != null) {
            for(Cookie cookie: cookies) {
                if(cookie.getName().equals(cookieKey)) {
                    tokenValue = cookie.getValue();
                    break;
                }
            }
        }

        return tokenValue;
    }
    private static String getPostData(HttpServletRequest request) {
        StringBuilder data = new StringBuilder();
        String line = null;
        BufferedReader reader = null;
        try {
            reader = request.getReader();
            while (null != (line = reader.readLine())) {
                data.append(line);
            }
        } catch (IOException e) {
            log.warn("{}", e.toString());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            }catch (Exception e){
                log.warn("{}",e.toString());
            }
        }
        return data.toString();
    }

    @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestURI = request.getRequestURI();
        String errPath="/error";
        if(requestURI.equals(errPath)) {
            return true;
        } else {
            String token = getAccessToken(request);
            if(StringUtils.isEmpty(token)) {
                log.warn("token is empty.");
                forwardToLogin(request, response);
                return false;
            }
            log.info("check token is valid, {}", token);
//            AccessToken accessToken = JSON.parseObject(token, AccessToken.class);
            String userInfoStr = accessTokenRedisMapper.getTokenInfo(token); //设置过期时间,30天
            if (StringUtils.isEmpty(userInfoStr)) {
                forwardToLogin(request, response);
                return false;
            }
//            if (null == userInfoStr) {
                // response.setCode(ResultCode.DISABLED).setMessage("token is invalid");
//                log.info("token is invalid, will 302 to get token.");// setCode ResultCode.DISABLED
//                JSONObject json = new JSONObject();
//                json.put("code", 302);
//                json.put("message", "token is invalid");
//                String result = json.toJSONString();
//                this.writeResponse(response, result);
//                return false;
//            }
            JSONObject userInfo = JSONObject.parseObject(userInfoStr);
            String phoneNumber = userInfo.getString("phoneNumber");
            String userID = userInfo.getString("userID");
            Integer plat = userInfo.getInteger("plat");
            log.info("user info: {}, phoneNumber: {}, userID: {}, plat: {}.", userInfoStr, phoneNumber, userID, plat);
            PlatUserHolder.getCurrentUser().set(new PlatUser(plat, phoneNumber,userID));
            return true;
        }
    }

    @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
        throws Exception {
//        CounterLogger.write(response, request.getRequestURI())
//        ThreadLocalManager.clear()
        super.postHandle(request, response, handler, modelAndView);
    }

    public void forwardToLogin(HttpServletRequest request, HttpServletResponse response) throws
        IOException {
        // 如果是移动端过来的请求的话，直接返回错误response，不redirect到login页面
        String plat = request.getParameter("plat");
        if (checkIsMobilePlat(plat)) {
            String result = PassportUtil.generateResultFromPassportError(PassportErrorCode.ACCESS_TOKEN_INVALID, null);
            writeResponse(response, result);
        } else {
            String url="";
            String host = request.getHeader("host1");
            if(host!=null) {
                url = "http://" + host;
            } else {
                // 历史request.getHeader("host")
                String referer = request.getHeader("referer");
                String routePath = request.getHeader("routePath");
                if(! StringUtils.isEmpty(routePath)) {
                    url = referer + "#" + routePath;
                }else {
                    url = referer;
                }
            }
            String redirectUrl = passportProperties.getLoginUrl() + "?" + "redirectURL=" + URLEncoder.encode(url, "UTF-8");
            if (checkAjax(request)) {
                // 如果是ajax请求的话，返回redirect的response
                JSONObject redirectJsonObject = new JSONObject();
                redirectJsonObject.put("redirectUrl", redirectUrl);

                String result = PassportUtil.generateResultFromPassportError(PassportErrorCode.ACCESS_TOKEN_INVALID, redirectJsonObject);
                writeResponse(response, result);
            } else {
                // 如果不是ajax的话，返回302跳转页面
                response.sendRedirect(redirectUrl);
                setCorsHeader(response);
            }
        }
    }
    public void showHeader() {
        //            String path = request.getContextPath();
//            String path2 = request.getServletPath();
//            String uri = request.getRequestURI();
//            log.info("path: {}, path2: {}, uri: {}.", path, path2, uri);
//            String params = request.getQueryString();
//            log.info("params: {}", params);
//            StringBuffer urlFull= request.getRequestURL();
//            log.info("url: {}",urlFull);

//            Enumeration<String> headerNames = request.getHeaderNames();
//            while(headerNames.hasMoreElements()) {
//                String key = headerNames.nextElement();
//                if(key.equalsIgnoreCase("Cookie")) {
//                    continue;
//                }
//                String value = request.getHeader(key);
//                log.info("k: {}, v: {}", key, value);
//            }
    }

    private boolean checkIsMobilePlat(String plat) {
        if(StringUtils.isEmpty(plat)) {
            log.debug("plat is web.");
            return false;
        }
        int platV;
        try {
            platV = Integer.parseInt(plat);
        }catch (Exception e) {
            log.warn("Exception: {}", plat);
            platV = 0;
        }
        if(Plat.MOBILE.getCode()==platV ||Plat.WECHATAPPLET.getCode()==platV || Plat.WECHAT_BCP.getCode()==platV) {
            log.debug("plat is mobile. {}",plat);
            return true;
        }else{
            log.debug("plat is web. {}", plat);
            return false;
        }
    }

    private boolean checkAjax(HttpServletRequest request) {
        if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
            log.info("request is ajax.");
            return true;
        } else {
            log.info("request is not ajax.");
            return false;
        }
    }

    private void writeResponse(HttpServletResponse response, String result) throws IOException {
        response.setContentType("application/json;" + "charset=UTF-8");
        PrintWriter responseWriter = response.getWriter();
        responseWriter.print(result);
        responseWriter.flush();
    }

    private void setCorsHeader(HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
    }
}
